#ifndef _IM_SERVER_COMET_CONNECTION_
#define _IM_SERVER_COMET_CONNECTION_

#include <string>

#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
#include <memory.h>
#include "ImServiceCommon_constants.h"

using namespace boost::asio;

namespace imserver {

extern std::string IM_REQ_END;
extern std::string IM_RES_END;

class SockConnection;
typedef boost::shared_ptr<SockConnection> SockConnectionPtr;

class SockConnection : public boost::enable_shared_from_this<SockConnection> {
public:
  static SockConnectionPtr Create(boost::asio::io_service& io_service);
  ~SockConnection();

  static bool isReadCompleted(const char * data, size_t len);
  static bool parseKeyValue(const std::string& data, std::map<std::string, std::string>& output);

  ip::tcp::socket& socket() {
    return socket_;
  }

  std::string remote_addr() const;

  bool isReadyForReceiveMsg() {
    return (valid_ && ready_);
  }

  void closeSocket() {
    valid_ = false;
    ready_ = false;
    socket_.close();
  }

  void Start();
  void AsyncRead();
  void AsyncWrite();
  void Abort();

  void WriteKickMsgAndClose(const char* data, size_t len);

  void WriteResponse(const std::string & response) {
    rep_str_ = response;
    write_buf_ = response.c_str();
    write_buf_begin_ = 0;
    write_buf_end_ = response.size();
    AsyncWrite();
  }

  void reset_read_buf() {
    memset(read_buf_, 0, kReadBufLength);
    read_buf_begin_ = 0;
    read_buf_end_ = 0;
  }

  boost::asio::io_service & io_service() {
    return io_service_;
  }
private:
  SockConnection(boost::asio::io_service& io_service);
  void HandleRead(const boost::system::error_code& error, size_t bytes_transferred);
  void HandleWrite(const boost::system::error_code& /*error*/, size_t /*bytes_transferred*/);
  bool onReadComplete();

  boost::asio::io_service & io_service_;
  ip::tcp::socket socket_;

  int64_t uid_;
  std::string version_;

  bool ready_;
  bool valid_;
  bool kicked_;

  enum { kReadBufLength = 4 * 1024 };

  char read_buf_[kReadBufLength];
  size_t read_buf_begin_, read_buf_end_;

  const char * write_buf_;
  size_t write_buf_begin_, write_buf_end_;
  std::string rep_str_;
};

}

#endif // _IM_SERVER_SOCK_CONNECTION_
